﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace PremisPublisher.Common
{
    /// <summary>
    /// 定制的rsa加密类
    /// 加密的文件在files节点下
    /// </summary>
    public class crypt_sql_files_reader
    {
        public static readonly crypt_sql_files_reader instance = new crypt_sql_files_reader();

        string XMLPATH = System.IO.Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "crypt_sql_files.xml");

        public IEnumerable<string> files;

        private string rsa_public_key = string.Empty;

        public static crypt_sql_files_reader GetInstance()
        { return instance; }

        private crypt_sql_files_reader()
        {
            files = ReadContent();
            rsa_public_key = Read_Rsa_public_key();
        }

        public void Reload() {
            files = ReadContent();
            rsa_public_key = Read_Rsa_public_key();
        }

        public string GetRSAPublicKey()
        {
            return rsa_public_key;
        }


        private string Read_Rsa_public_key()
        {
            return XDocument.Load(XMLPATH).Element("crypted").Element("public_key").Element("RSAKeyValue").ToString();
        }

        private IEnumerable<string> ReadContent()
        {
            return (from item in XDocument.Load(XMLPATH).Element("crypted").Element("files").Elements("file")
                    select item.Value
                        ).ToList();
        }

        /// <summary>
        /// 加密，添加文件
        /// </summary>
        /// <param name="filepath"></param>
        /// <returns>错误返回1，成功返回0</returns>
        public int AddFile(string filepath) {
            try
            {
                files = ReadContent();

                //不重复加密
                if (files.Count(c=>c.Equals(filepath)) > 0) {
                    return 1;
                }

                if (rsa_crypt(filepath) == 0)
                {
                    var doc = XDocument.Load(XMLPATH);
                    XElement record = new XElement("file", filepath);
                    doc.Element("crypted").Element("files").Add(record);
                    doc.Save(XMLPATH);

                    Reload();

                    return 0;
                }
                else return 1;

            }
            catch (Exception)
            {
                return 1;
            }
        }


        /// <summary>
        /// 分段RSA加密
        /// </summary>
        /// <param name="filepath"></param>
        /// <returns>错误返回1， 成功返回0</returns>
        private int rsa_crypt(string filepath) {

            var content = System.IO.File.ReadAllText(filepath);

            try
            {
                var crypted_content = RSACrypto.Encrypt(content, rsa_public_key);

                System.IO.FileInfo fi = new System.IO.FileInfo(filepath);
                fi.IsReadOnly = false;
                fi.Delete();

                //用加密的内容替换
                System.IO.File.WriteAllText(filepath, crypted_content);

                System.IO.FileInfo nfi = new System.IO.FileInfo(filepath);
                nfi.IsReadOnly = true;
            }
            catch (Exception)
            {
                System.IO.File.WriteAllText(filepath, content);
                return 1;
            }

            return 0;
        }
    }
}
